<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, user-scalable=no">
  <meta name="description" content="API docs for the saveLayer method from the Canvas class, for the Dart programming language.">
  <title>saveLayer method - Canvas class - dart:ui library - Dart API</title>
  <!-- required because all the links are pseudo-absolute -->
  <base href="../..">

  <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500,400i,400,300|Source+Sans+Pro:400,300,700" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="static-assets/github.css">
  <link rel="stylesheet" href="static-assets/styles.css">
  <link rel="icon" href="static-assets/favicon.png">
  
</head>

<body>

<div id="overlay-under-drawer"></div>

<header id="title">
  <button id="sidenav-left-toggle" type="button">&nbsp;</button>
  <ol class="breadcrumbs gt-separated dark hidden-xs">
    <li><a href="index.html">shake</a></li>
    <li><a href="dart-ui/dart-ui-library.html">dart:ui</a></li>
    <li><a href="dart-ui/Canvas-class.html">Canvas</a></li>
    <li class="self-crumb">saveLayer method</li>
  </ol>
  <div class="self-name">saveLayer</div>
  <form class="search navbar-right" role="search">
    <input type="text" id="search-box" autocomplete="off" disabled class="form-control typeahead" placeholder="Loading search...">
  </form>
</header>

<main>

  <div id="dartdoc-sidebar-left" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left">
    <header id="header-search-sidebar" class="hidden-l">
      <form class="search-sidebar" role="search">
        <input type="text" id="search-sidebar" autocomplete="off" disabled class="form-control typeahead" placeholder="Loading search...">
      </form>
    </header>
    
    <ol class="breadcrumbs gt-separated dark hidden-l" id="sidebar-nav">
      <li><a href="index.html">shake</a></li>
      <li><a href="dart-ui/dart-ui-library.html">dart:ui</a></li>
      <li><a href="dart-ui/Canvas-class.html">Canvas</a></li>
      <li class="self-crumb">saveLayer method</li>
    </ol>
    
    <h5>Canvas class</h5>
    <ol>
      <li class="section-title"><a href="dart-ui/Canvas-class.html#constructors">Constructors</a></li>
      <li><a href="dart-ui/Canvas/Canvas.html">Canvas</a></li>
    
      <li class="section-title inherited">
        <a href="dart-ui/Canvas-class.html#instance-properties">Properties</a>
      </li>
      <li class="inherited"><a href="dart-core/Object/hashCode.html">hashCode</a></li>
      <li class="inherited"><a href="dart-core/Object/runtimeType.html">runtimeType</a></li>
    
      <li class="section-title"><a href="dart-ui/Canvas-class.html#instance-methods">Methods</a></li>
      <li><a href="dart-ui/Canvas/clipPath.html">clipPath</a></li>
      <li><a href="dart-ui/Canvas/clipRect.html">clipRect</a></li>
      <li><a href="dart-ui/Canvas/clipRRect.html">clipRRect</a></li>
      <li><a href="dart-ui/Canvas/drawArc.html">drawArc</a></li>
      <li><a href="dart-ui/Canvas/drawAtlas.html">drawAtlas</a></li>
      <li><a href="dart-ui/Canvas/drawCircle.html">drawCircle</a></li>
      <li><a href="dart-ui/Canvas/drawColor.html">drawColor</a></li>
      <li><a href="dart-ui/Canvas/drawDRRect.html">drawDRRect</a></li>
      <li><a href="dart-ui/Canvas/drawImage.html">drawImage</a></li>
      <li><a href="dart-ui/Canvas/drawImageNine.html">drawImageNine</a></li>
      <li><a href="dart-ui/Canvas/drawImageRect.html">drawImageRect</a></li>
      <li><a href="dart-ui/Canvas/drawLine.html">drawLine</a></li>
      <li><a href="dart-ui/Canvas/drawOval.html">drawOval</a></li>
      <li><a href="dart-ui/Canvas/drawPaint.html">drawPaint</a></li>
      <li><a href="dart-ui/Canvas/drawParagraph.html">drawParagraph</a></li>
      <li><a href="dart-ui/Canvas/drawPath.html">drawPath</a></li>
      <li><a href="dart-ui/Canvas/drawPicture.html">drawPicture</a></li>
      <li><a href="dart-ui/Canvas/drawPoints.html">drawPoints</a></li>
      <li><a href="dart-ui/Canvas/drawRawAtlas.html">drawRawAtlas</a></li>
      <li><a href="dart-ui/Canvas/drawRawPoints.html">drawRawPoints</a></li>
      <li><a href="dart-ui/Canvas/drawRect.html">drawRect</a></li>
      <li><a href="dart-ui/Canvas/drawRRect.html">drawRRect</a></li>
      <li><a href="dart-ui/Canvas/drawShadow.html">drawShadow</a></li>
      <li><a href="dart-ui/Canvas/drawVertices.html">drawVertices</a></li>
      <li><a href="dart-ui/Canvas/getSaveCount.html">getSaveCount</a></li>
      <li><a href="dart-ui/Canvas/restore.html">restore</a></li>
      <li><a href="dart-ui/Canvas/rotate.html">rotate</a></li>
      <li><a href="dart-ui/Canvas/save.html">save</a></li>
      <li><a href="dart-ui/Canvas/saveLayer.html">saveLayer</a></li>
      <li><a href="dart-ui/Canvas/scale.html">scale</a></li>
      <li><a href="dart-ui/Canvas/skew.html">skew</a></li>
      <li><a href="dart-ui/Canvas/transform.html">transform</a></li>
      <li><a href="dart-ui/Canvas/translate.html">translate</a></li>
      <li class="inherited"><a href="dart-core/Object/noSuchMethod.html">noSuchMethod</a></li>
      <li class="inherited"><a href="dart-core/Object/toString.html">toString</a></li>
    
      <li class="section-title inherited"><a href="dart-ui/Canvas-class.html#operators">Operators</a></li>
      <li class="inherited"><a href="dart-core/Object/operator_equals.html">operator ==</a></li>
    
    
    
    </ol>
  </div><!--/.sidebar-offcanvas-->

  <div id="dartdoc-main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
      <div><h1>saveLayer method</h1></div>

    <section class="multi-line-signature">
      <span class="returntype">void</span>
            <span class="name ">saveLayer</span>
(<wbr><span class="parameter" id="saveLayer-param-bounds"><span class="type-annotation"><a href="dart-ui/Rect-class.html">Rect</a></span> <span class="parameter-name">bounds</span>, </span> <span class="parameter" id="saveLayer-param-paint"><span class="type-annotation"><a href="dart-ui/Paint-class.html">Paint</a></span> <span class="parameter-name">paint</span></span>)
      
    </section>
    <section class="desc markdown">
      <p>Saves a copy of the current transform and clip on the save stack, and then
creates a new group which subsequent calls will become a part of. When the
save stack is later popped, the group will be flattened into a layer and
have the given <code>paint</code>'s <a href="dart-ui/Paint/colorFilter.html">Paint.colorFilter</a> and <a href="dart-ui/Paint/blendMode.html">Paint.blendMode</a>
applied.</p>
<p>This lets you create composite effects, for example making a group of
drawing commands semi-transparent. Without using <a href="dart-ui/Canvas/saveLayer.html">saveLayer</a>, each part of
the group would be painted individually, so where they overlap would be
darker than where they do not. By using <a href="dart-ui/Canvas/saveLayer.html">saveLayer</a> to group them
together, they can be drawn with an opaque color at first, and then the
entire group can be made transparent using the <a href="dart-ui/Canvas/saveLayer.html">saveLayer</a>'s paint.</p>
<p>Call <a href="dart-ui/Canvas/restore.html">restore</a> to pop the save stack and apply the paint to the group.</p>
<h2 id="using-savelayer-with-clips">Using saveLayer with clips</h2>
<p>When a rectangular clip operation (from <a href="dart-ui/Canvas/clipRect.html">clipRect</a>) is not axis-aligned
with the raster buffer, or when the clip operation is not rectalinear (e.g.
because it is a rounded rectangle clip created by <a href="dart-ui/Canvas/clipRRect.html">clipRRect</a> or an
arbitrarily complicated path clip created by <a href="dart-ui/Canvas/clipPath.html">clipPath</a>), the edge of the
clip needs to be anti-aliased.</p>
<p>If two draw calls overlap at the edge of such a clipped region, without
using <a href="dart-ui/Canvas/saveLayer.html">saveLayer</a>, the first drawing will be anti-aliased with the
background first, and then the second will be anti-aliased with the result
of blending the first drawing and the background. On the other hand, if
<a href="dart-ui/Canvas/saveLayer.html">saveLayer</a> is used immediately after establishing the clip, the second
drawing will cover the first in the layer, and thus the second alone will
be anti-aliased with the background when the layer is clipped and
composited (when <a href="dart-ui/Canvas/restore.html">restore</a> is called).</p>
<p>For example, this <code>CustomPainter.paint</code> method paints a clean white
rounded rectangle:</p>
<pre class="language-dart"><code class="language-dart">void paint(Canvas canvas, Size size) {
  Rect rect = Offset.zero &amp; size;
  canvas.save();
  canvas.clipRRect(new RRect.fromRectXY(rect, 100.0, 100.0));
  canvas.saveLayer(rect, new Paint());
  canvas.drawPaint(new Paint()..color = Colors.red);
  canvas.drawPaint(new Paint()..color = Colors.white);
  canvas.restore();
  canvas.restore();
}
</code></pre>
<p>On the other hand, this one renders a red outline, the result of the red
paint being anti-aliased with the background at the clip edge, then the
white paint being similarly anti-aliased with the background <em>including
the clipped red paint</em>:</p>
<pre class="language-dart"><code class="language-dart">void paint(Canvas canvas, Size size) {
  // (this example renders poorly, prefer the example above)
  Rect rect = Offset.zero &amp; size;
  canvas.save();
  canvas.clipRRect(new RRect.fromRectXY(rect, 100.0, 100.0));
  canvas.drawPaint(new Paint()..color = Colors.red);
  canvas.drawPaint(new Paint()..color = Colors.white);
  canvas.restore();
}
</code></pre>
<p>This point is moot if the clip only clips one draw operation. For example,
the following paint method paints a pair of clean white rounded
rectangles, even though the clips are not done on a separate layer:</p>
<pre class="language-dart"><code class="language-dart">void paint(Canvas canvas, Size size) {
  canvas.save();
  canvas.clipRRect(new RRect.fromRectXY(Offset.zero &amp; (size / 2.0), 50.0, 50.0));
  canvas.drawPaint(new Paint()..color = Colors.white);
  canvas.restore();
  canvas.save();
  canvas.clipRRect(new RRect.fromRectXY(size.center(Offset.zero) &amp; (size / 2.0), 50.0, 50.0));
  canvas.drawPaint(new Paint()..color = Colors.white);
  canvas.restore();
}
</code></pre>
<p>(Incidentally, rather than using <a href="dart-ui/Canvas/clipRRect.html">clipRRect</a> and <a href="dart-ui/Canvas/drawPaint.html">drawPaint</a> to draw
rounded rectangles like this, prefer the <a href="dart-ui/Canvas/drawRRect.html">drawRRect</a> method. These
examples are using <a href="dart-ui/Canvas/drawPaint.html">drawPaint</a> as a proxy for "complicated draw operations
that will get clipped", to illustrate the point.)</p>
<h2 id="performance-considerations">Performance considerations</h2>
<p>Generally speaking, <a href="dart-ui/Canvas/saveLayer.html">saveLayer</a> is relatively expensive.</p>
<p>There are a several different hardware architectures for GPUs (graphics
processing units, the hardware that handles graphics), but most of them
involve batching commands and reordering them for performance. When layers
are used, they cause the rendering pipeline to have to switch render
target (from one layer to another). Render target switches can flush the
GPU's command buffer, which typically means that optimizations that one
could get with larger batching are lost. Render target switches also
generate a lot of memory churn because the GPU needs to copy out the
current frame buffer contents from the part of memory that's optimized for
writing, and then needs to copy it back in once the previous render target
(layer) is restored.</p>
<p>See also:</p><ul><li><a href="dart-ui/Canvas/save.html">save</a>, which saves the current state, but does not create a new layer
for subsequent commands.</li><li><a href="dart-ui/BlendMode-class.html">BlendMode</a>, which discusses the use of <a href="dart-ui/Paint/blendMode.html">Paint.blendMode</a> with
<a href="dart-ui/Canvas/saveLayer.html">saveLayer</a>.</li></ul>
    </section>
    
    <section class="summary source-code" id="source">
      <h2><span>Implementation</span></h2>
      <pre class="language-dart"><code class="language-dart">void saveLayer(Rect bounds, Paint paint) {
  assert(paint != null);
  if (bounds == null) {
    _saveLayerWithoutBounds(paint._objects, paint._data);
  } else {
    assert(_rectIsValid(bounds));
    _saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
               paint._objects, paint._data);
  }
}</code></pre>
    </section>

  </div> <!-- /.main-content -->

  <div id="dartdoc-sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right">
  </div><!--/.sidebar-offcanvas-->

</main>

<footer>
  <span class="no-break">
    shake 0.1.0
  </span>

  
</footer>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="static-assets/typeahead.bundle.min.js"></script>
<script src="static-assets/highlight.pack.js"></script>
<script src="static-assets/URI.js"></script>
<script src="static-assets/script.js"></script>


</body>

</html>
